import { ComponentProps } from './component';
import { signal, computed, effect } from 'alien-signals';

/**
 * Signal接口，表示一个可以读取和更新的值
 */
export interface Signal<T = any> {
  (): T;
  (value: T): void;
}

/**
 * 创建一个响应式信号
 * @param initialValue 初始值
 * @returns 一个可以读取和更新的信号函数
 */
export function createSignal<T>(initialValue?: T): Signal<T | undefined> {
  return signal(initialValue);
}

/**
 * 创建一个计算信号，其值依赖于其他信号
 * @param getter 计算函数，返回计算结果
 * @returns 一个只读的信号函数
 */
export function createComputed<T>(getter: (previousValue?: T) => T): Signal<T> {
  return computed(getter);
}

/**
 * 创建一个副作用，当依赖的信号变化时自动运行
 * @param fn 副作用函数
 * @returns 一个停止副作用的函数
 */
export function createEffect(fn: () => void): () => void {
  return effect(fn);
}

/**
 * 响应式组件的基础类，集成了signals支持
 */
export abstract class ReactiveComponent {
  private effects: Array<() => void> = [];
  private isMounted: boolean = false;

  /**
   * 组件挂载时调用
   * 子类可以重写此方法以执行初始化操作
   */
  onMount(): void {
    this.isMounted = true;
  }

  /**
   * 组件卸载时调用
   * 清除所有副作用
   */
  onUnmount(): void {
    this.isMounted = false;
    // 清除所有副作用
    this.effects.forEach(stop => stop());
    this.effects = [];
  }

  /**
   * 创建一个与组件生命周期绑定的副作用
   * @param fn 副作用函数
   */
  public createReactiveEffect(fn: () => void): void {
    // 如果组件尚未挂载，先存储effect函数，等待挂载后再创建
    if (!this.isMounted) {
      // 延迟创建effect，直到组件挂载后
      const originalOnMount = this.onMount.bind(this);
      this.onMount = () => {
        originalOnMount();
        const stop = effect(fn);
        this.effects.push(stop);
      };
    } else {
      // 如果组件已挂载，立即创建effect
      const stop = effect(fn);
      this.effects.push(stop);
    }
  }

  /**
   * 检查组件是否已挂载
   */
  protected get mounted(): boolean {
    return this.isMounted;
  }
}

/**
 * 为组件属性创建响应式代理
 * @param props 组件属性
 * @returns 响应式属性代理
 */
export function makePropsReactive(props: ComponentProps): ComponentProps {
  const reactiveProps: ComponentProps = {};
  
  // 代理属性访问
  return new Proxy(reactiveProps, {
    get(target, key: string) {
      if (key in target) {
        return target[key];
      }
      return props[key];
    },
    set(target, key: string, value) {
      target[key] = value;
      return true;
    },
    has(target, key: string) {
      return key in target || key in props;
    }
  });
}

/**
 * 为元素创建响应式更新函数
 * @param element 元素实例
 * @param updateFn 更新函数
 * @returns 一个绑定到元素的响应式更新函数
 */
export function createReactiveUpdater<T>(
  element: T,
  updateFn: (element: T, ...args: any[]) => void
): (...args: any[]) => void {
  return (...args: any[]) => {
    updateFn(element, ...args);
  };
}